import React, { useState, useEffect } from 'react';
import { Space, Modal, Card, message } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { connect, Dispatch, history, Location } from 'umi';
import { PageContainer } from '@ant-design/pro-layout';
import ProCard from '@ant-design/pro-card';
import { CQ_DETAIL } from '@/actions/cq';
import { CQ_TRADE_INIT, CQ_ADD_TRADE, TRADE_TASK, ALLOT_CQ_TRADE, 
  PREALLOC_TRADE_TASK, UPDATE_TRADE_TASK, CQ_DELETE_TRADE, DELETE_TRADE_TASK, IMPORT_TRADE_TASK } from '@/actions/workbench';
import { AButton, AGrid, AGridButtonCallBackModel } from '@/components/SelfComp';
import { ConnectState } from '@/models/connect';
import { AppItem } from '@/types/app';
import { CqTradeItem } from '@/types/cq';
import { DataItem } from '@/types/global';
import { TradeItem } from '@/types/trade';
import { UndoAllotTradeTaskState, CqBaseInfoFormValue, TradeTaskItem, CqDetailInfoFormValue, 
  CqUndoTaskType } from '@/types/workbench';
import { getCurrentLoginUser } from '@/utils/authority';
import { EMPTY_CQ_UNDO_TASK, EMPTY_CQ_BASE_INFO, EMPTY_CQ_DETAIL_INFO } from './common';
import { CqBaseInfoForm, CqTradeInfoForm, TradeTaskModal, ImportTradeTaskModal } from './components';

interface AllotCqTradeProps {
  dispatch: Dispatch;
  location: Location;
  auditorData: DataItem[];
  developerData: DataItem[];
  testerData: DataItem[];
  tradeTaskNameData: DataItem[];
  tradeList: TradeItem[];
  // tradeTaskList: TradeTaskItem[];
  // tradeTaskTotal: number;
  loading: boolean;
  /** 初始化参数查询 */
  queryLoading: boolean;
  /** 查询交易对应的开发任务 */
  queryTaskLoading: boolean;
  taskHandleLoading: boolean;
  systemData: DataItem[];
  clusterData: DataItem[];
  appList: AppItem[];
  /** 批量导入交易任务 */
  importLoading: boolean;
}

const columns: ColumnsType<CqTradeItem> = [
  {
    title: '交易功能码',
    dataIndex: 'funcCode',
    width: 200
  },
  {
    title: '交易名称',
    dataIndex: 'funcName',
    ellipsis: true,
  },
  {
    title: '交易路径',
    dataIndex: 'funcAction',
    ellipsis: true,
  },
  {
    title: '预分配任务数量',
    dataIndex: 'taskNum',
    width: 200
  },
];

/**
 * 需求分配交易任务
 */
const AllotCqTrade: React.FC<AllotCqTradeProps> = (props) => {
  // 当前表格勾选信息
  const [formData, setFormData] = useState<CqUndoTaskType>(EMPTY_CQ_UNDO_TASK);
  // 需求基础信息表单
  const [baseInfo, setBaseInfo] = useState<CqBaseInfoFormValue>(EMPTY_CQ_BASE_INFO);
  const [detailInfo, setDetailInfo] = useState<CqDetailInfoFormValue>(EMPTY_CQ_DETAIL_INFO);
  const [tradeTaskModalVisible, setTradeTaskModalVisible] = useState<boolean>(false);
  const [tradeTaskModalTitle, setTradeTaskModalTitle] = useState<string>('');
  const [tradeTaskList, setTradeTaskList] = useState<TradeTaskItem[]>([]);
  // 交易表格勾选
  const [selectedRows, setSelectedRows] = useState<CqTradeItem[]>([]);
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  // 本地交易列表
  const [localTradeList, setLocalTradeList] = useState<CqTradeItem[]>([]);
  // 手工分页
  const [pageSize, setPageSize] = useState<number>(10);
  // const [trades, setTrades] = useState<CqTradeItem[]>([]);
  // 交易任务导入弹窗
  const [importTradeTaskModalVisible, setImportTradeTaskModalVisible] = useState<boolean>(false);

  useEffect(() => {
    console.log('AllotCqTrade.useEffect');
    // 获取页面传值
    const { location } = props;
    const { state } = location as { state: UndoAllotTradeTaskState };
    // 未传值，直接返回登录
    if (!state) {
      goLogin();
      return;
    }
    const cqUndoTaskInfo = state && state.cqUndoTaskInfo;
    const cqDetailInfo = state && state.cqDetailInfo;
    // 需求下挂的交易列表，可能有值，可能没值
    // 当交易添加到表格，但没有继续处理就返回了
    const cqTradeList = state && state.tradeList;
    if (cqUndoTaskInfo && cqDetailInfo) {
      // 满足条件，开始查询页面参数
      const { dispatch } = props;
      const { cqCode, cqName, systemCode, clstCode, appCode } = cqUndoTaskInfo;
      // 根据系统，集群，应用查询对应的交易列表
      dispatch(CQ_TRADE_INIT({
        systemCode,
        clstCode,
        appCode,
        pageNum: 1,
        pageSize: 1000
      }));
      const { auditor, devStartDate, devEndDate, sitStartDate, sitEndDate, uatStartDate, uatEndDate, prdDate } = cqDetailInfo;
      // 需求基础信息表单所需的数据
      const baseInfo: CqBaseInfoFormValue = {
        cqCode,
        cqName,
        systemCode,
        clstCode,
        appCode,
        auditor
      };
      // 需求详细日期信息
      const detailInfo: CqDetailInfoFormValue = {
        cqCode,
        devStartDate,
        devEndDate,
        sitStartDate,
        sitEndDate,
        uatStartDate,
        uatEndDate,
        prdDate
      };
      setBaseInfo(baseInfo);
      setDetailInfo(detailInfo);
      setFormData(cqUndoTaskInfo);
      setLocalTradeList(cqTradeList);
      // fetchCqTradeByPage(1, pageSize, cqTradeList);
    } else {
      Modal.warn({
        title: '警告',
        content: '非法访问，请检查数据',
        okText: '确定',
        onOk: () => goBack()
      });
    }
  }, []);

  const goLogin = () => {
    message.warning('不允许直接访问，请通过我的待办交易进入');
    history.replace('/user/login');
  }

  /**
   * 退出按钮
   */
  const goBack = () => {
    history.goBack();
  }

  const addTrade2Table = async (record: CqTradeItem) => {
    // 交易功能码栏位的值添加到表格中
    // 如果交易已添加到表格中，则不允许重复添加
    const { tradeId } = record;
    let flag = false;
    for (let i = 0; i < localTradeList.length; i += 1) {
      const tmpItem =  localTradeList[i];
      if (tmpItem.tradeId === tradeId) {
        flag = true;
        break;
      }
    }
    if (flag) {
      const { funcCode } = record;
      message.warn(`交易[${funcCode}]已添加至表格中，请勿重复添加`);
      return false;
    }
    // 与服务端通讯添加交易，但状态为中间态
    const { dispatch } = props;
    // 上送任务id和实例id是为了保障任务信息的完整性，不被篡改和代理任务
    const { actTaskId, actInstId, cqId } = formData;
    const values = {
      actTaskId,
      actInstId,
      cqId,
      tradeId
    };
    // 获取当前登录用户，作为任务处理人
    const res = await dispatch(CQ_ADD_TRADE({
      ...values,
    }));
    if (res) {
      const tmpList = [
        ...localTradeList
      ];
      tmpList.push(record);
      setLocalTradeList(tmpList);
      // fetchCqTradeByPage(1, pageSize, tmpList);
      return true;
    }
    return false;
  }

  /**
   * 需求分配交易最后的提交按钮
   * 
   * @returns 
   */
  const handleSubmit = () => {
    if (localTradeList.length === 0) {
      message.warn('需求尚未分配交易，不能提交');
      return;
    }
    // console.log('Received values of form: ');
    // 判断是否有交易没有分配交易任务
    let flag = true;
    let tmpFuncCode;
    // console.info(localTradeList);
    for (let i = 0; i < localTradeList.length; i += 1) {
      const tmpItem =  localTradeList[i];
      if (tmpItem.taskNum === 0) {
        flag = false;
        tmpFuncCode = tmpItem.funcCode;
        break;
      }
    }
    if (!flag) {
      message.warn(`交易[${tmpFuncCode}]未分配开发任务，不可提交`);
      return;
    }
    // console.info('AllotCqTrade.handleSubmit2');
    // 准备数据，调用回调函数提交服务端处理
    allotCqTrade();
  }

  const allotCqTrade = async () => {
    // 与服务端通讯
    const { dispatch } = props;
    const { actTaskId, actInstId, cqId } = formData;
    const userCode = getCurrentLoginUser();
    const values = {
      actTaskId,
      actInstId,
      cqId,
      userCode
    };
    // 获取当前登录用户，作为任务处理人
    const res = await dispatch(ALLOT_CQ_TRADE({
      ...values,
    }));
    if (res) {
      // 是否重置表单
      message.success('需求分配交易任务成功', 1)
      .then(() => onExit());
    }
  }

  /**
   * 退出按钮
   */
  const onExit = () => {
    history.goBack();
  }

  /**
   * 表格勾选回调函数
   * @param {*} rows 表格选中数据集合
   */
  const onSelectRow = (keys: React.Key[], rows: CqTradeItem[]) => {
    setSelectedRowKeys(keys);
    setSelectedRows(rows);
  };

  /**
   * 手动获取分页数据
   * @param {*} pageSize 每页记录条数
   * @param {*} pageNum 页码
   * @param {*} userList 用户列表数据
   */
  const fetchCqTradeByPage = (pageNum: number, pageSize: number, tradeList: CqTradeItem[]) => {
    if (tradeList && tradeList.length > 0) {
      const tmpTradeList: CqTradeItem[] = tradeList.slice((pageNum - 1) * pageSize, pageNum * pageSize);
      // setTrades(tmpTradeList);
      return tmpTradeList;
    }
    return [];
  }

  /**
   * 页码改变的回调，参数是改变后的页码及每页条数
   * @param page 改变后的页码，上送服务器端
   * @param pageSize 每页数据条数
   */
  const onPageNumAndSizeChange = (page: number, pageSize: number) => {
    // console.log(page, pageSize);
    setPageSize(pageSize);
    // fetchCqTradeByPage(page, pageSize, localTradeList);
  };

  /**
   * 工具栏左边的按钮
   * @returns 按钮集合
   */
  const renderLeftButton = () => {
    const { queryTaskLoading, importLoading } = props;
    const disabled = selectedRowKeys.length === 1;
    return (
      <>
        <AButton
          disabled={!disabled}
          title='勾选一个交易，点击分配任务'
          code='task'
          pageCode='cq-trade'
          name='交易分配任务'
          onClick={openTradeTaskModal}
          loading={queryTaskLoading}
        />
        <AButton
          type='primary'
          code='import'
          pageCode='cq-trade'
          name='批量导入交易任务'
          onClick={openImportTradeModal}
          loading={importLoading}
        />
      </>
    );
  }

  /**
   * 处理按钮点击回调事件
   * @param {*} payload 数据包
   */
  const handleBtnCallBack = (callBackModel: AGridButtonCallBackModel<CqTradeItem>) => {
    // btn 按钮
    // keys 表格勾选数组
    const { code, keys } = callBackModel;
    // 删除
    if (code === 'delete') {
      // 调用删除服务，删除勾选数据
      // console.info(keys);
      deleteTrades(keys);
      return;
    }
  }

  /**
   * 打开任务分配窗口
   */
  const openTradeTaskModal = async () => {
    // 表格选中内容
    // console.info('openTradeTaskModal');
    if (selectedRowKeys.length === 0) {
      message.warn('请先选择一条数据!');
      return;
    }
    if (selectedRowKeys.length > 1) {
      message.warn('只能选择一条数据!');
      return;
    }
    const { cqId } = formData;
    // 获取交易id
    const tradeId = selectedRowKeys[0];
    // console.info('tradeId', tradeId);
    // 查询交易已分配任务列表
    const { dispatch } = props;
    const res = await dispatch(TRADE_TASK({
      cqId,
      tradeId,
      pageSize: 100,
      pageNum: 1
    }));
    // console.info(res);
    if (res) {
      // 这里试试dispatch的回调方法
      // 只有查询成功才会弹窗
      const { funcCode } = selectedRows[0];
      const modalTitle = `交易${funcCode}任务窗口`;
      const { rows } = res;
      setTradeTaskModalTitle(modalTitle);
      // 查询全部任务，然后手动分页
      setTradeTaskList([...rows]);
      setTradeTaskModalVisible(true);
    }
  }

  const deleteTrades = async (keys: React.Key[]) => {
    // console.info('deleteTrades', keys);
    const tradeId = keys[0] as string;
    const { cqId, actInstId, actTaskId } = formData;
    const { dispatch } = props;
    const values = {
      cqId,
      tradeId,
      actInstId,
      actTaskId
    };
    const res = await dispatch(CQ_DELETE_TRADE({
      ...values,
    }));
    if (res) {
      // 本地直接删除？？
      let index = -1;
      const tmpList = [
        ...localTradeList
      ];
      const len = tmpList.length;
      for (let i = 0; i < len; i += 1) {
        const item = tmpList[i];
        if (tradeId === item.tradeId) {
          index = i;
          break;
        }
      }
      tmpList.splice(index, 1);
      setLocalTradeList([...tmpList]);
      // fetchCqTradeByPage(1, pageSize, tmpList);
    }
  }

  /**
   * 给交易分配开发任务，只有通讯成功才会关闭窗口及将按钮设置为可点击
   */
  const handleTradeTaskModalOk = (taskNum: number) => {
    // console.info('handleTradeTaskModalOk');
    // 更新交易已分配任务数量
    // 修改本页面表格中的已分配任务数量
    // 待定
    // 是否将更新任务数量放到弹窗确定事件中
    const currentTrade = selectedRows[0];
    const tmpList = updateTaskNum(currentTrade, taskNum);
    setLocalTradeList(tmpList);
    // fetchCqTradeByPage(1, pageSize, tmpList);
    // 取消勾选
    // setSelectedRowKeys([]);
    // setSelectedRows([]);
    setTradeTaskModalVisible(false);
  }

  /**
   * 弹窗取消事件，无动作，仅清空弹窗数据
   */
  const handleTradeTaskModalCancel = (taskNum: number) => {
    // console.info('handleTradeTaskModalCancel');
    if (taskNum) {
      const currentTrade = selectedRows[0];
      const tmpList = updateTaskNum(currentTrade, taskNum);
      setLocalTradeList(tmpList);
      // fetchCqTradeByPage(1, pageSize, tmpList);
    }
    // setTradeTaskList([]);
    setTradeTaskModalVisible(false);
  }

  const tradeTaskHandle = async (handleType: string, records: TradeTaskItem | TradeTaskItem[]) => {
    // 与服务端通讯添加交易，但状态为中间态
    const { dispatch } = props;
    const { cqId } = formData;
    const currentTrade = selectedRows[0];
    const { tradeId, funcCode } = currentTrade;
    // console.info('tradeTaskHandle', handleType, records);
    // console.info('tradeTaskHandle', typeof records);
    if (handleType === 'add' && typeof records === 'object') {
      // 新增任务
      const record = records as TradeTaskItem;
      const values = {
        cqId,
        tradeId,
        funcCode,
        ...record
      };
      const res = await dispatch(PREALLOC_TRADE_TASK({
        ...values,
      }));
      if (res) {
        return true;
      }
    } else if (handleType === 'edit' && typeof records === 'object') {
      // 修改任务信息
      const record = records as TradeTaskItem;
      const values = {
        cqId,
        tradeId,
        funcCode,
        ...record
      };
      const res = await dispatch(UPDATE_TRADE_TASK({
        ...values,
      }));
      if (res) {
        return true;
      }
    } else if (handleType === 'delete' && typeof records === 'object') {
      // 删除任务
      const record = records as TradeTaskItem;
      const { taskId, taskHash } = record;
      const values = {
        cqId,
        tradeId,
        taskId,
        taskHash
      };
      const res = await dispatch(DELETE_TRADE_TASK({
        ...values,
      }));
      if (res) {
        return true;
      }
    }
    return false;
  }

  /**
   * 更新交易已分配任务数
   * 
   * @param currentTrade 当前交易
   * @param taskNum 任务数
   */
  const updateTaskNum = (currentTrade: CqTradeItem, taskNum: number) => {
    const { tradeId } = currentTrade;
    let index = -1;
    const tmpList = [
      ...localTradeList
    ];
    const len = tmpList.length;
    for (let i = 0; i < len; i += 1) {
      const item = tmpList[i];
      if (tradeId === item.tradeId) {
        index = i;
        break;
      }
    }
    const newRecord: CqTradeItem = {
      ...currentTrade,
      taskNum,
    }
    // console.info('符合条件的数组下标为', index);
    tmpList.splice(index, 1, newRecord);
    // console.info('准备提交的数据', localTradeList);
    // setLocalTradeList(tmpList);
    return tmpList;
  }

  const openImportTradeModal = () => {
    // 先判断是否手工添加了交易
    // 若手工添加了，则提示删除
    if (localTradeList.length > 0) {
      message.warning('请先删除已添加的交易，在导入');
      return;
    }
    setImportTradeTaskModalVisible(true);
  }

  const downloadTemplateFile = (fileName: string) => {
    console.info(fileName);
    message.success('模板下载成功');
  }

  /**
   * 批量导入弹窗确认事件
   * 
   * @param formDataEx 表单数据
   */
  const handleImportModalOk = async (formDataEx: FormData) => {
    console.log(formDataEx.get('data'));
    if (formDataEx && formDataEx.has('data')) {
      const data = JSON.parse(formDataEx.get('data') as string);
      const { actTaskId, actInstId, cqId } = formData;
      const newData = {
        ...data,
        actTaskId,
        actInstId,
        cqId,
      }
      formDataEx.set('data', JSON.stringify(newData));
      console.log(formDataEx.get('data'));
      const { dispatch } = props;
      const res = await dispatch(IMPORT_TRADE_TASK(formDataEx));
      if (res) {
        message.success('导入成功');
        setImportTradeTaskModalVisible(false);
        // 查询交易列表
        const { dispatch } = props;
        const res2 = await dispatch(CQ_DETAIL({
          cqId,
          status: '3'
        }));
        // console.info(res);
        if (res2) {
          const { result } = res2;
          if (result) {
            const { tradeList } = result;
            if (tradeList) {
              // 更新交易表格
              setLocalTradeList([...tradeList]);
            }
          }
        }
      }
    } else {
      message.error('缺失导入数据，无法导入，请检查！');
    }
  }

  const handleImportModalCancel = () => {
    setImportTradeTaskModalVisible(false);
  };

  const { auditorData, tradeList, systemData, clusterData, appList, loading, queryLoading } = props;
  const { tradeTaskNameData, developerData, testerData, taskHandleLoading, importLoading } = props;
  const code = 'cq-trade';
  const tradeTotal = localTradeList.length;
  const tradeTaskTotal = tradeTaskList.length;
  const rowKey = (record: CqTradeItem) => record.tradeId;
  const pkField = 'tradeId';
  // console.info(localTradeList);
  const trades = fetchCqTradeByPage(1, pageSize, localTradeList);

  return (
    <PageContainer title='需求分配交易任务'>
      <Space direction='vertical' size='middle' style={{ display: 'flex' }}>
        <ProCard
          title='需求基本信息'
        >
          <CqBaseInfoForm
            colon={false}
            loading={false}
            auditorData={auditorData}
            systemData={systemData}
            clusterData={clusterData}
            appList={appList}
            formData={baseInfo}
          />
        </ProCard>
        <ProCard title='分配交易任务'>
          <CqTradeInfoForm
            colon={false}
            loading={loading}
            queryLoading={queryLoading}
            tradeData={tradeList}
            addTrade2Table={addTrade2Table}
            onSubmit={handleSubmit}
            onCancel={onExit}
          />
          <Card title='交易列表' style={{ marginBottom: 0 }}>
            <AGrid
              code={code}
              actionColumnFixed={'right'}
              btnCallBack={handleBtnCallBack}
              delConfirmMsg='确定删除选中记录？若交易已分配开发任务，将一并删除！'
              renderLeftButton={renderLeftButton}
              columns={columns}
              rowKey={rowKey}
              pkField={pkField}
              dataSource={trades}
              loading={queryLoading}
              total={tradeTotal}
              scroll={{x:1000}}
              onSelectRow={onSelectRow}
              onPageNumAndSizeChange={onPageNumAndSizeChange}
            />
          </Card>
        </ProCard>
      </Space>
      {
        !tradeTaskModalVisible ? null :
        <TradeTaskModal
          colon={false}
          modalTitle={tradeTaskModalTitle}
          modalWidth={1100}
          modalVisible={tradeTaskModalVisible}
          formData={detailInfo}
          loading={false}
          tradeTaskNameData={tradeTaskNameData}
          developerData={developerData}
          testerData={testerData}
          tradeTaskList={tradeTaskList}
          tradeTaskTotal={tradeTaskTotal}
          onHandlerOK={handleTradeTaskModalOk}
          onHandlerCancel={handleTradeTaskModalCancel}
          taskHandleLoading={taskHandleLoading}
          tradeTaskHandle={tradeTaskHandle}
        />
      }
      {
        importTradeTaskModalVisible  && (
          <ImportTradeTaskModal
            colon={false}
            modalTitle='批量导入交易任务'
            modalWidth={1000}
            modalVisible={importTradeTaskModalVisible}
            loading={importLoading}
            onHandlerOK={handleImportModalOk}
            onHandlerCancel={handleImportModalCancel}
            downloadTemplateFile={downloadTemplateFile}
          />
        )
      }
    </PageContainer>
  );
}

export default connect(({ users, systems, workbenchs, cqs, loading }: ConnectState) => ({
  auditorData: users.auditorData,
  developerData: users.developerData,
  testerData: users.testerData,
  tradeTaskNameData: systems.tradeTaskNameData,
  // 根据系统，集群，应用查询的交易列表
  tradeList: workbenchs.tradeList,
  systemData: systems.systemData,
  clusterData: systems.clusterData,
  appList: cqs.appList,
  loading: loading.effects['workbenchs/allotCqTrade'],
  queryLoading: loading.effects['workbenchs/fetchCqTradeInitParams'] || loading.effects['workbenchs/cqAddTrade'] || loading.effects['workbenchs/fetchCqDetail'],
  queryTaskLoading: loading.effects['workbenchs/fetchTradeTasks'] || loading.effects['workbenchs/cqDeleteTrade'],
  taskHandleLoading: loading.effects['workbenchs/preAllocTradeTask'] || loading.effects['workbenchs/updateTradeTask'],
  importLoading: loading.effects['workbenchs/importTradeTask'],
}))(AllotCqTrade);